'''
Created on 28/04/2013

@author: cristian
'''
from flask import Flask, session, redirect, url_for, escape, request, Response
from pm import app
from pm.models.Fases import Fases
from pm.models.Items import Items
from pm.models.Proyectos import Proyectos
from pm.models.SolicitudCambio import SolicitudCambio
from pm.models.UsuariosRolesFases import UsuariosRolesFases
from pm.models.UsuariosRoles import UsuariosRoles
from pm.models.RolesPermisos import RolesPermisos
from pm.models.Permisos import Permisos
from pm.models.Roles import Roles
from . import jsonifiedview
from . import ensureParams
from pm.database import db
from pm.models.TiposItemFases import TiposItemFases
from sqlalchemy import func
from sqlalchemy import or_
'''
Metodo que lista las fases con que cuenta un determinado proyecto
este metodo recibe un id de proyecto para que se realice la consulta
'''


@app.route('/fases/listarfasesproyecto', methods=['GET', 'POST']) 
@jsonifiedview
def listarFasesProyectos():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    queryFases = Fases.query.filter(Fases.id_proyecto == params['id'])
    queryFases = queryFases.filter(Fases.id_fase == params['id_fase']) if 'id_fase' in params else queryFases
    queryFases = queryFases.filter(Fases.nombre.like('%' + params['nombre'] + '%')) if 'nombre' in params else queryFases
    queryFases = queryFases.filter(Fases.descripcion.like('%' + params['descripcion'] + '%')) if 'descripcion' in params else queryFases 
    queryFases = queryFases.filter(Fases.estado.like('%' + params['estado'] + '%')) if 'estado' in params else queryFases 
    queryFases = queryFases.filter(Fases.activo.like('%' + params['activo'] + '%')) if 'activo' in params else queryFases
    queryFases = queryFases.filter(Fases.cantidad_lb.like('%' + params['cantidad_lb'] + '%')) if 'cantidad_lb' in params else queryFases  
    queryFases = queryFases.filter(Fases.cantidad_items.like('%' + params['cantidad_items'] + '%')) if 'cantidad_items' in params else queryFases  
    return queryFases.order_by(Fases.id_fase).all()

@app.route('/fases/retornarfase', methods=['GET', 'POST']) 
@jsonifiedview
def retornarFase():
    '''
       Metodo que que retorna la fase seleccionada por el usuario
       @param id_fase: identidicador de la fase a retornar
       
    '''
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    
    if not ensureParams(params, ['id_fase']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    try:
        id_fase= int(str(params['id_fase']))
        fase= Fases.query.filter(Fases.id_fase==id_fase).one()
        response={"success":True,"fase":fase}
        return response
    except Exception, e:
        response = {"success" : False , "msg" : "Ups.!!Ocurrio un error al intentar obtener la  Fase seleccionada!!"}
        return response    
    

@app.route('/fases/listarfasesporusuario', methods=['GET', 'POST']) 
@jsonifiedview
def listarFasesPorUsuario():
    '''
       Metodo que lista las fases relacionadas a un usuario
       @param id_usuario: identificador del usuario
       @param id_proyecto: identificador del proyecto en cuestion
       
    '''
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    
    if not ensureParams(params, ['id_usuario', 'id_proyecto']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    try:
        id_usuario= int(str(params['id_usuario']))
        id_proyecto=int(str(params['id_proyecto']))
        
        
        usuarioRol= UsuariosRoles.query.filter(UsuariosRoles.id_usuario==id_usuario).all()
        esLider=False
        
        rol= Roles.query.filter(Roles.nombre=='LIDER_PROYECTO').filter(Roles.activo==True).one()
        for ur in usuarioRol:
            usuarioRolesFasesAux = UsuariosRolesFases.query.filter(UsuariosRolesFases.id_proyecto==params['id_proyecto']).filter(UsuariosRolesFases.id_usuario_rol==ur.id_usuario_rol).all()
            for urfaux in usuarioRolesFasesAux:
                if(ur.id_rol==rol.id_rol and ur.activo==True):
                    esLider=True
        fases=[]
        if esLider:
            fasesLider = Fases.query.filter(Fases.id_proyecto==id_proyecto)
            fasesLider = fasesLider.filter(Fases.id_fase == params['id_fase']) if 'id_fase' in params else fasesLider
            fasesLider = fasesLider.filter(Fases.nombre.like('%' + params['nombre'] + '%')) if 'nombre' in params else fasesLider
            fasesLider = fasesLider.filter(Fases.descripcion.like('%' + params['descripcion'] + '%')) if 'descripcion' in params else fasesLider 
            fasesLider = fasesLider.filter(Fases.estado.like('%' + params['estado'] + '%')) if 'estado' in params else fasesLider
            fasesLider = fasesLider.all()
            for f in fasesLider:
                if f not in fases:
                    fases.append(f)
            return fases
    
       
        for ur in usuarioRol:
            usuarioRolFase= UsuariosRolesFases.query.filter(UsuariosRolesFases.id_proyecto==id_proyecto).filter(UsuariosRolesFases.id_usuario_rol==ur.id_usuario_rol).all()
            for urf in usuarioRolFase:
                if (ur.id_usuario_rol== urf.id_usuario_rol and urf.activo_fase == True and urf.activo==True):
                    fase= Fases.query.filter(Fases.id_proyecto==id_proyecto).filter(Fases.id_fase==urf.id_fase)
                    fase = fase.filter(Fases.id_fase == params['id_fase']) if 'id_fase' in params else fase
                    fase = fase.filter(Fases.nombre.like('%' + params['nombre'] + '%')) if 'nombre' in params else fase
                    fase = fase.filter(Fases.descripcion.like('%' + params['descripcion'] + '%')) if 'descripcion' in params else fase 
                    fase = fase.filter(Fases.estado == params['estado']) if 'estado' in params else fase 
                    fase = fase.filter(Fases.activo.like('%' + params['activo'] + '%')) if 'activo' in params else fase
                    fase = fase.filter(Fases.cantidad_lb.like('%' + params['cantidad_lb'] + '%')) if 'cantidad_lb' in params else fase
                    fase = fase.filter(Fases.cantidad_items.like('%' + params['cantidad_items'] + '%')) if 'cantidad_items' in params else fase  
                    fase  = fase.all()
                    if fase:
                        for f in fase:
                            if f not in fases:
                                fases.append(f)
        return fases
    except Exception, e:
        response = {}
        response = {"success" : False , "msg" : "Ups, ha ocurrido un error", "msg2":e}
        return response 
    

@app.route('/fases/crear', methods=['GET', 'POST']) 
@jsonifiedview
def crearFase():
    '''
       Metodo que Crea una nueva Fase
       @param nombre: nombre de la fase
       @param descripcion: descripcion de la fase
       @param posicion: posicion de la fase
       @param estado : estado de la fase
       @param id_proyecto: identificador del proyecto en cuestion  
    '''
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    
    if not ensureParams(params, ['nombre', 'descripcion', 'posicion', 'id_proyecto','activo']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes"} 
        return response
    try:
        proyecto= Proyectos.query.filter(Proyectos.id_proyecto == params['id_proyecto']).one()
        
        pos=int(str(params['posicion']))
                
        if pos > proyecto.cantidad_fases:
            response={"success" : False , "msg" : "La posicion que desea agregar esta fuera de rango!!"}
            return response
        if pos < 1:
            response={"success": False,"msg": "La posicion introducida es invalida!!"}
            return response
        
        fasesProyecto= Fases.query.filter(Fases.id_proyecto == params['id_proyecto'])
        band= False
        for fp in fasesProyecto:
            if fp.posicion == pos:
                band= True
        if band== False:
            fases = Fases(params['nombre'], params['descripcion'], params['posicion'],1, params['id_proyecto'],params['activo'],0,0)
            db.session.add(fases)
            db.session.commit()
            response = {"success" : True , "msg" : "Creacion exitosa!!"} 
            return response
        cantidad_fases= Fases.query.filter(Fases.id_proyecto== params['id_proyecto']).count()
        if(proyecto.cantidad_fases==cantidad_fases):
            proyecto=Proyectos.query.filter(Proyectos.id_proyecto== params['id_proyecto']).update({'estado':2})
            db.session.commit()
        response={"success": False,"msg": "La posicion introducida ya es utilizada!!"}
        return response
    except Exception, e:
        db.session.rollback()
        response = {"success" : False , "msg" : "Error en la base de datos!!"}
        return response 

@app.route('/fases/modificar', methods=['GET', 'POST']) 
@jsonifiedview
def modificarFase():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    
    '''
        Metodo que modifica una  Fase
       @param id: identificador de la fase a modificar 
       @param nombre: nombre de la fase
       @param descripcion: descripcion de la fase
    '''
    if not ensureParams(params, ['id','nombre', 'descripcion']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes"} 
        return response
    try:
        fase = Fases.query.filter(Fases.id_fase == params['id']).one()
        if fase.estado!=1 and fase.estado!=2:
            response ={"success" : True , "msg" : "La fase ya no puede ser modificada"}
            return response
            
        fases = Fases.query.filter(Fases.id_fase == params['id']).update({'nombre':params['nombre'],
        'descripcion':params['descripcion']})
        db.session.commit()
        response ={"success" : True , "msg" : "Actualizacion exitosa!!"} 
        return response
    except Exception, e:
        db.session.rollback()
        response ={"success" : False , "msg" : "Error en la base de datos!!"}
        return response


@app.route('/fases/cambiarestadofase', methods=['GET', 'POST']) 
@jsonifiedview
def cambiarEstadoFase():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    '''
        Metodo que cambia el estado de una fase
       @param id: identificador de la fase a modificar 
       @param estado: estado a modificar
    '''
        
    if not ensureParams(params, ['id',  'estado']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes"} 
        return response
    try:
               
        fases = Fases.query.filter(Fases.id_fase == params['id']).update({'estado':params['estado']})
        db.session.commit()
        response ={"success" : True , "msg" : "Cambio de estado realizado exitosamente!!"} 
        return response
    except Exception, e:
        db.session.rollback()
        response ={"success" : False , "msg" : "Error en la base de datos!!"}
        return response
    TiposItemFases
@app.route('/fases/activardesactivar', methods=['GET', 'POST']) 
@jsonifiedview
def activardesactivarFase():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    '''
        Metodo para activar/desactivar una fase
       @param id: identificador de la fase a modificar 
       @param activo: determina si se inactivara o no
    '''
        
    if not ensureParams(params, ['id',  'activo']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes"} 
        return response
    try:
        faseActual= Fases.query.filter(Fases.id_fase==params['id']).one()
        proyectoAsociado = Proyectos.query.filter(Proyectos.id_proyecto==faseActual.id_proyecto).one()
        contadorFasesActivas = Fases.query.filter(Fases.id_proyecto==proyectoAsociado.id_proyecto).filter(Fases.activo==True).count()
        
        if contadorFasesActivas == proyectoAsociado.cantidad_fases:
            if params['activo']:
                response={"success" : False, "msg":"La fase ya no puede desactivarse!!"}                          
                return response
            
        fases = Fases.query.filter(Fases.id_fase == params['id']).one()#.update({'activo':params['activo']})
        proyecto = Proyectos.query.filter(Proyectos.id_proyecto==fases.id_proyecto).one()
        if proyecto.estado == 1:
            fases=Fases.query.filter(Fases.id_fase == params['id']).update({'activo':params['activo']})
            db.session.commit()
            response ={"success" : True , "msg" : "Realizado exitosamente!!"} 
            return response
        response={"success":False,"msg":"El proyecto ya se ha iniciado, no se puede desactivar!!"}
        return response
    except Exception, e:
        db.session.rollback()
        response ={"success" : False , "msg" : "Error en la base de datos!!"}
        return response

@app.route('/fases/importarfase', methods=['GET', 'POST']) 
@jsonifiedview
def importarFase():
    '''
        Metodo para importar una fase
       @param id_fase_a_importar: identificador de la fase a importar 
       @param id_fase_actual: determina si se inactivara o no
    '''
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    
    if not ensureParams(params, ['id_fase_a_importar', 'id_fase_actual']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes"} 
        return response
    
    tiposItemFases = TiposItemFases.query.filter(TiposItemFases.id_fase == params ['id_fase_a_importar']).all()
    try:
        for tif in tiposItemFases:
            tipnew= TiposItemFases(tif.id_tipo_item, params['id_fase_actual'],True)
            db.session.add(tipnew)
            db.session.commit()
            response = {"success" : True, "msg" : "Importacion Exitosa"} 
            return response
        
    except Exception, e:
        db.session.rollback()
        response = {"success" : False , "msg" : "Error en la Base de datos"} 
        return response
    
@app.route('/fases/cerrarfase', methods=['GET', 'POST']) 
@jsonifiedview
def cerrarFase():
    '''
        Metodo para importar una fase
       @param id_fase: identificador de la fase que sera importada 
    '''
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    
    if not ensureParams(params, ['id_fase']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes"} 
        return response
    
    fase=Fases.query.filter(Fases.id_fase==params['id_fase']).one()
    try:
        if fase.estado != 2:
            response = {"success" : False , "msg" : "La fase no se encuentra en estado en Desarrollo"} 
            return response
           
        cantidad= Items.query.filter(Items.id_fase == fase.id_fase).filter(Items.estado == 3).count()
        if cantidad != fase.cantidad_items:
            response = {"success" : False , "msg" : "Todavia Existen Items sin asociar a una linea base"} 
            return response
        fase.estado= 3
        db.session.commit()       
        response = {"success" : True , "msg" : "Finalizacion exitosa de la fase"}  
        return response
    except Exception, e:
        response = {"success" : False , "msg" : "Ups Ha ocurrido un error"} 
        return response

@app.route('/fases/abrir', methods=['GET', 'POST']) 
@jsonifiedview
def abrirFase():
    '''
        Metodo para abrir una fase
       @param id_fase: identificador de la fase que quiere ser abierta
       @param id_usuario: id usuario del usuario que queiere abrir la fase 
    '''
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    resp = []
    
    if not ensureParams(params, ['id_fase', 'id_usuario']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes"} 
        return response
    
    esLider = False
    fase = Fases.query.filter(Fases.id_fase==params['id_fase']).one()
    proyecto = Proyectos.query.filter(Proyectos.id_proyecto==fase.id_proyecto).one()
    usuariosRolesFasesL = UsuariosRolesFases.query.filter(UsuariosRolesFases.id_proyecto == proyecto.id_proyecto).filter(UsuariosRolesFases.activo == True).all()
    for urf in usuariosRolesFasesL:
        usuariosroles = UsuariosRoles.query.filter(UsuariosRoles.id_usuario_rol==urf.id_usuario_rol).filter(UsuariosRoles.id_usuario== params['id_usuario']).filter(UsuariosRoles.id_rol==2).all()
        if(usuariosroles):
            esLider = True;
            
    if(esLider==True):
        rolespermisoslider = RolesPermisos.query.filter(RolesPermisos.id_rol==2).all()
        for rpl in rolespermisoslider:
            permisoslider = Permisos.query.filter(Permisos.id_permiso==rpl.id_permiso).one()
            if permisoslider.nombre not in resp:
                resp.append(permisoslider.nombre)
    else:
        #Vemos todos los roles que tiene asignado en ese proyecto
        usuariosRolesFases = UsuariosRolesFases.query.filter(UsuariosRolesFases.id_fase == params['id_fase']).filter(UsuariosRolesFases.activo_fase == True).all()
        for urf in usuariosRolesFases:
            usuarioRol = UsuariosRoles.query.filter(UsuariosRoles.id_usuario_rol == urf.id_usuario_rol).one()
            if usuarioRol.id_usuario == int(str(params['id_usuario'])):
                rolesPermisos = RolesPermisos.query.filter(RolesPermisos.id_rol == usuarioRol.id_rol).filter(RolesPermisos.activo == True).all()
                for rp in rolesPermisos: 
                    permisos = Permisos.query.filter(Permisos.id_permiso == rp.id_permiso).one()
                    if permisos.nombre not in resp:
                        resp.append(permisos.nombre)
    if not resp:                
        response = {"success" : False, "resp" : resp}
    else:
        response = {"success" : True, "resp" : resp}
        
    return response

@app.route('/fases/activarDesactivarRolxFase', methods=['GET', 'POST']) 
@jsonifiedview
def activarDesactivarRolxFase():
    """
        Permite activar o desactivar un ROL Asignado a un Usuario
    """
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    
   
    
    if not ensureParams(params,['id_fase','id_usuario','id_rol','activo']): 
        response ={"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    
    try:
       
        id_fase= int(str(params['id_fase']))
        fase= Fases.query.filter(Fases.id_fase==id_fase ).one()
        id_proyecto= fase.id_proyecto
        id_usuario=int(str(params['id_usuario']))
        id_rol= int(str(params['id_rol']))
        activo= params['activo']
        usuarioRoles= UsuariosRoles.query.filter(UsuariosRoles.id_usuario==id_usuario).filter(UsuariosRoles.id_rol==id_rol).one()
        
        solicitudCambio = SolicitudCambio.query.filter(SolicitudCambio.id_usuario == id_usuario).filter(or_(SolicitudCambio.estado == 'En Votacion', SolicitudCambio.estado == 'Enviado' )).first()
        if solicitudCambio:
            response ={"success" : False , "msg" : "El usuario no puede ser desactivado ya que tiene una solictud en votacion"} 
            return response
        
        usuariosRolesFases = UsuariosRolesFases.query.filter(UsuariosRolesFases.id_fase == id_fase).filter(UsuariosRolesFases.id_usuario_rol==usuarioRoles.id_usuario_rol).update({'activo_fase':activo})
        db.session.commit()
        response ={"success" : True , "msg" : "Actualizacion exitosa!!"} 
        return response
    
    except Exception, e:
        db.session.rollback()
        response ={"success" : False , "msg" : "Ups.!! Hubo un error al intentar modificar el estado de la relacion!!"}
        return response 
    
@app.route('/fases/estadorelacionrolxfase', methods=['GET', 'POST']) 
@jsonifiedview
def estadoRelacionRolxFase():
    '''
        Trae el estado de un rol asociado a un proyecto
    '''
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response ={}
    #Comprobamos si el usuario se encuentra logueado
    
    
    try:
        id_fase= int(str(params['id_fase']))
        fase= Fases.query.filter(Fases.id_fase==id_fase).one()
        id_proyecto=fase.id_proyecto
        id_usuario= int(str(params['id_usuario']))
        id_rol= int(str(params['id_rol']))
      
        
        usuarioRoles= UsuariosRoles.query.filter(UsuariosRoles.id_usuario==id_usuario).filter(UsuariosRoles.id_rol==id_rol).one()
        usuarioRolesFases= UsuariosRolesFases.query.filter(UsuariosRolesFases.id_proyecto== id_proyecto).filter(UsuariosRolesFases.id_fase==id_fase).filter(UsuariosRolesFases.id_usuario_rol==usuarioRoles.id_usuario_rol).one()
        
        response ={"success" : True ,"activo":usuarioRolesFases.activo_fase}
        return response
    except Exception, e:
        response ={"success" : False , "msg" : "Ups!! Hubo un error al intentar desactivar al usuario!!"}
        return response   



@app.route('/fases/asignarusuarioafase', methods=['GET', 'POST']) 
@jsonifiedview
def asignarUsuarioAFase():
    '''
       Metodo que Crea una nueva Fase
       @param id_fase: identificador de la fase 
       @param id_rol: identificador del rol 
       @param id_usuario: identificador del usuario
       
    '''
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
    
    if not ensureParams(params, ['id_fase', 'id_rol', 'id_usuario']): 
        response = {"success" : False , "msg" : "Parametros Insuficientes"} 
        return response
    try:
        id_fase= params['id_fase']
        id_rol= params['id_rol']
        id_usuario= params['id_usuario']
       
        fase= Fases.query.filter(Fases.id_fase== id_fase).one()
        id_proyecto= fase.id_proyecto
        
        usuarioRoles= UsuariosRoles.query.filter(UsuariosRoles.id_rol == id_rol).filter(UsuariosRoles.id_usuario == id_usuario).one()
        usuRoleFase= UsuariosRolesFases.query.filter(UsuariosRolesFases.id_proyecto== id_proyecto).filter(UsuariosRolesFases.id_usuario_rol== usuarioRoles.id_usuario_rol).filter(or_ (UsuariosRolesFases.id_fase!= id_fase, UsuariosRolesFases.id_fase==None)).all()
        for usurolesfase in usuRoleFase:
            if (usurolesfase.id_fase==None):
                         
                usuRolFase= UsuariosRolesFases.query.filter(UsuariosRolesFases.id_proyecto== id_proyecto).filter(UsuariosRolesFases.id_usuario_rol== usuarioRoles.id_usuario_rol).update({'activo_fase':True,'id_fase':id_fase})
                db.session.commit()
                response = {"success" : True , "msg" : "Modificacion  exitosa!!"} 
                return response
            if (usurolesfase.id_fase!=None):
                usurlfase= UsuariosRolesFases(usuarioRoles.id_usuario_rol,id_fase,id_proyecto,True,True)
                db.session.add(usurlfase)
                db.session.commit()
                response = {"success" : True , "msg" : "Creacion exitosa!!"} 
                return response
        
    except Exception, e:
        db.session.rollback()
        response = {"success" : False , "msg" : "Ups, ha ocurrido un error"}
        return response 

